/**
 * Vector2.java
 * 
 * @date: 2012-02-28
 * @author: Xiaoyu Guo (MUN# 200982155)
 * This file is part of the course project for COMP 6752, 
 * Application of Computer Graphics. All the file is written
 * by myself.
 */
package mun.cs6752.project.model;

/** Defines a vector with size of 2.
 * Vector2 is used to represent a Cartesian coordinate.
 * @author Xiaoyu Guo
 */
public class Vector2 extends Vector {
    private static final int SIZE = 2;
    private static final int INDEX_X = 0;
    private static final int INDEX_Y = 1;
    
    /** 
     * @param source
     */
    public Vector2(double[] source) {
        super(source);
        
        if(size != SIZE){
            throw new IllegalArgumentException("size must be 2");
        }
    }
    
    public Vector2(){
        super(SIZE);
    }
    
    public Vector2(double x, double y){
        super(SIZE);
        setX(x);
        setY(y);
    }
    
    public Vector2(Vector value){
        super(SIZE);

        checkNull(value);
        if(value.size < SIZE){
            throw new IllegalArgumentException("size must be 2");
        }
        
        setX(value.get(INDEX_X));
        setY(value.get(INDEX_Y));
    }

    public double getX(){
        return get(INDEX_X);
    }
    
    public void setX(double x){
        set(INDEX_X, x);
    }
    
    public double getY(){
        return get(INDEX_Y);
    }
    
    public void setY(double y){
        set(INDEX_Y, y);
    }
    
    /** 2D translation by offset
     * @param tx offset on x axis
     * @param ty offset on y axis
     * @return
     */
    public Vector2 translate(double tx, double ty){
        return new Vector2(getX() + tx, getY() + ty);
    }
    
    /** 2D translation using vector offset
     * @param t vector containing offset values on both axis
     * @return
     */
    public Vector2 translate(Vector2 t){
        return add(t);
    }
    
    /** Vector addition
     * @param value
     * @return
     */
    public Vector2 add(Vector2 value){
        checkNull(value);
        return new Vector2(getX() + value.getX() , getY() + value.getY());
    }
    
    public Vector2 minus(Vector2 value){
        checkNull(value);
        return new Vector2(getX() - value.getX(), getY() - value.getY());
    }
    
    @Override
    public Vector2 getUnitVector(){
        double length = getLength();
        if(length == 0){
            return this;
        }
        return new Vector2(getX() / length, getY() / length);
    }
    
    /** Scalar multiplication
     * @param value
     * @return
     */
    @Override
    public Vector2 multiply(double value){
        return new Vector2(getX() * value, getY() * value);
    }
    
    /** Scaling
     * @param sx scaling ratio on x axis
     * @param sy scaling ratio on y axis
     * @return
     */
    public Vector2 scale(double sx, double sy){
        return new Vector2(getX() * sx, getY() * sy);
    }
    
    /** Rotation about (0, 0)
     * @param theta the value of rotation
     * @return
     */
    public Vector2 rotate(double theta){
        return new Vector2(
            getX() * Math.cos(theta) - getY() * Math.sin(theta),
            getX() * Math.sin(theta) + getY() * Math.cos(theta)
        );
    }
    
    /** Gets the homogeneous vector
     * @return (x, y, 1)
     */
    public Vector3 getHomogeneous(){
        return new Vector3(getX(), getY(), 1);
    }
}
